package pers.cj.pdos.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.exception.CustomException;
import pers.cj.pdos.mapper.*;
import pers.cj.pdos.service.IHouseInService;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author chenj
 * @since 2020-01-14
 *
 */
@Service
public class HouseInServiceImpl extends ServiceImpl<HouseInMapper, HouseIn> implements IHouseInService {
    @Autowired
    HouseInMapper houseInMapper;
    @Autowired
    HouseInGoodsMapper houseInGoodsMapper;
    @Autowired
    HouseInPacketMapper houseInPacketMapper;
    @Autowired
    HouseInPacketGoodsMapper houseInPacketGoodsMapper;

    @Autowired
    HouseWaitInMapper houseWaitInMapper;
    @Autowired
    HouseWaitInGoodsMapper houseWaitInGoodsMapper;
    @Autowired
    HouseWaitInPacketMapper houseWaitInPacketMapper;
    @Autowired
    GoodsSnMapper goodsSnMapper;
    @Autowired
    GoodsSnLogMapper goodsSnLogMapper;
    @Autowired
    OrderRuleMapper orderRuleMapper;
    @Autowired
    GoodsStockMapper goodsStockMapper;
    @Autowired
    InGoodsGoodsMapper inGoodsGoodsMapper;
    @Autowired
    GoodsCostMapper goodsCostMapper;
    @Autowired
    GoodsTransferMapper goodsTransferMapper;
    @Autowired
    GoodsTransferGoodsMapper goodsTransferGoodsMapper;
    @Autowired
    HouseMapper houseMapper;
    @Autowired
    SettAccountMapper settAccountMapper;

    @Override
    public boolean checkNo(String no, String companyId) {
        return houseInMapper.selectCount(new QueryWrapper<HouseIn>().eq("company_id",companyId).eq("no",no)) > 0;
    }

    @Override
    public void insert(HouseIn houseIn, List<HouseInGoods> houseInGoodsList, List<GoodsSn> goodsSnList, List<GoodsSnLog> goodsSnLogList,
                       List<HouseInPacket> houseInPacketList,List<HouseInPacketGoods> houseInPacketGoodsList) {
        houseInMapper.insert(houseIn);

        if (!Utils.isEmpty(houseInGoodsList)) {
            houseInGoodsMapper.insertBatch(houseInGoodsList);
        }

        if (!Utils.isEmpty(houseInPacketList)) {
            houseInPacketMapper.insertBatch(houseInPacketList);
            houseInPacketGoodsMapper.insertBatch(houseInPacketGoodsList);
        }

        HouseInVo vo = houseInMapper.getVoById(houseIn.getId());

        Boolean locking = houseMapper.selectById(vo.getHouseId()).getLocking();
        if (locking!=null && locking) {
            throw new CustomException("仓库被锁定，无法入库");
        }

        //入库 运费 余额-
        if (!Utils.isEmpty(vo.getSettAccountId()) && vo.getDeliveryAmt()!= null){
            settAccountMapper.addBalance(vo.getDeliveryAmt().negate(), vo.getSettAccountId());
        }

        //处理待入库单
        processHouseWaitIn(1,vo);
        //增加库存
        processStock(1,vo);

        //增加序列号
        if (!Utils.isEmpty(goodsSnList)) {
            goodsSnMapper.insertBatch(goodsSnList);
            goodsSnLogMapper.insertBatch(goodsSnLogList);
        }


        updateGoodsTransferStatus(vo);
    }

    @Override
    public List<HouseInVo> listVo(String companyId,
                                  Integer page,
                                  Integer limit,
                                  Boolean close,
                                  Integer type,
                                  String search,
                                  String no,
                                  String linkNo,
                                  String goodsName,
                                  String remark,
                                  String unitName,
                                  Date makeTime1,
                                  Date makeTime2,
                                  String makeUserId,
                                  String userStoreId,
                                  String userId,
                                  Date date1,
                                  Date date2,
                                  String storeId,
                                  String houseId) {
        return houseInMapper.listVo(companyId,
                Utils.genPage(page,limit),
                limit,
                close,
                type,
                search,
                no,
                linkNo,
                goodsName,
                remark,
                unitName,
                makeTime1,
                makeTime2,
                makeUserId,
                userStoreId,
                userId,
                date1,
                date2,
                storeId,
                houseId);
    }

    @Override
    public long count(String companyId,
                      Boolean close,
                      Integer type,
                      String search,
                      String no,
                      String linkNo,
                      String goodsName,
                      String remark,
                      String unitName,
                      Date makeTime1,
                      Date makeTime2,
                      String makeUserId,
                      String userStoreId,
                      String userId,
                      Date date1,
                      Date date2,
                      String storeId,
                      String houseId) {
        return houseInMapper.count(companyId,
                close,
                type,
                search,
                no,
                linkNo,
                goodsName,
                remark,
                unitName,
                makeTime1,
                makeTime2,
                makeUserId,
                userStoreId,
                userId,
                date1,
                date2,
                storeId,
                houseId);
    }

    @Override
    public HouseInVo getVoById(String id) {
        HouseInVo entity = houseInMapper.getVoById(id);
        return entity;
    }

    @Override
    public List<HouseInVo> listVoByIds(List<String> ids) {
        return houseInMapper.listVoByIds(ids);
    }

    @Override
    public List<HouseInVo> listVoByHouseWaitIn(String houseWaitInId) {
        return houseInMapper.listVoByHouseWaitIn(houseWaitInId);
    }

    @Override
    public void close(HouseIn houseIn) {
        HouseInVo vo = houseInMapper.getVoById(houseIn.getId());


        //入库作废 运费 余额+
        if (!Utils.isEmpty(vo.getSettAccountId()) && vo.getDeliveryAmt()!= null){
            settAccountMapper.addBalance(vo.getDeliveryAmt(), vo.getSettAccountId());
        }

        processStock(2,vo);

        //处理sn号
        //关闭进货单需要sn号需要处与出库状态
        List<GoodsSn> list = PdosUtils.genGoodsSnList(vo.getHouseInGoodsVoList());
        if (!Utils.isEmpty(list)) {
            goodsSnMapper.outByList(vo.getHouseId(), list);
        }

        //处理待入库单
        processHouseWaitIn(2,vo);

        //关闭单据本身
        houseIn.setClose(true);
        houseInMapper.updateById(houseIn);


        updateGoodsTransferStatus(vo);
    }

    @Override
    public boolean checkByLinkId(String linkId) {
        return houseInMapper.countByLinkId(linkId) > 0;
    }

    @Override
    public boolean checkClose(HouseIn houseIn) {
        return houseInMapper.selectCount(new QueryWrapper<HouseIn>().eq("id",houseIn.getId()).eq("close",true)) > 0;
    }

    private void updateGoodsTransferStatus(HouseInVo vo){
        if (vo.getType()==3){
            long hasInNumber = houseWaitInGoodsMapper.countHasInNumberByGoodsTransferId(vo.getGoodsTransferId());
            long number = goodsTransferGoodsMapper.countNumber(vo.getGoodsTransferId());
            GoodsTransfer goodsTransfer = new GoodsTransfer();
            goodsTransfer.setId(vo.getGoodsTransferId());
            if (hasInNumber >= number) {
                //待入库单全部入库
                goodsTransfer.setInStatus(3);
            } else if (hasInNumber == 0){//全部等待入库
                goodsTransfer.setInStatus(1);
            } else {
                goodsTransfer.setInStatus(2);
            }
            //改变调拨单的入库状态
            goodsTransferMapper.updateById(goodsTransfer);
        }
    }


    /**
     * 处理库存
     * @param type
     * @param vo
     */
    private void processStock(int type, HouseInVo vo) {
        String companyId = vo.getCompanyId();

        if (vo.getType() == 1){
            //进货单对应的入库，需要操作成本表
            processGoodsCost(type,vo);
        }

        GoodsUtil goodsUtil = new GoodsUtil(vo.getHouseId(), vo.getHouseInGoodsVoList(), vo.getHouseInPacketVoList());
        List<GoodsStock> goodsStockList = new ArrayList<>();
        for ( Map.Entry<String,BigDecimal> entry: goodsUtil.getAllGoodsNumberMap().entrySet()) {
            String goodsId = entry.getKey();
            BigDecimal number = entry.getValue();
            if (type == 2) {
                //销售是减少库存的动作，所以需要减少库存
                number = number.negate();
            }

            GoodsStock goodsStock = new GoodsStock();
            goodsStock.setId(UuidUtils.getUUID());
            goodsStock.setGoodsId(goodsId);
            goodsStock.setHouseId(vo.getHouseId());
            goodsStock.setNum(number);
            goodsStock.setTime(new Date());
            goodsStock.setCompanyId(companyId);
            goodsStockList.add(goodsStock);
        }
        goodsStockMapper.insertBatch(goodsStockList);
    }

    private void processGoodsCost(int type,HouseInVo vo){


        //获取进货单对应的商品单价,计入成本价表
        List<InGoodsGoods> inGoodsGoodsList = inGoodsGoodsMapper.selectList(
                new QueryWrapper<InGoodsGoods>()
                        .eq("in_goods_id",vo.getInGoodsId())
                        .eq("company_id",vo.getCompanyId()));

        Map<String,InGoodsGoods> map = DataUtil.genMap("goodsId",inGoodsGoodsList);

        List<GoodsCost> goodsCostList = new ArrayList<>();
        for (HouseInGoodsVo hgv : vo.getHouseInGoodsVoList()) {
            //进货单入库，则要计算其成本
            //金额为单价乘以数量(入库单的单位)
            BigDecimal number = hgv.getNumber().multiply(hgv.getTimes());
            BigDecimal inGoodsPrice = map.get(hgv.getGoodsId()).getPrice();
            BigDecimal amount = hgv.getNumber().multiply(inGoodsPrice);//数量乘以单价
            if (type == 2) {
                amount = amount.negate();//作废单据，则要减去金额
                number = number.negate();
            }
            GoodsCost goodsCost = new GoodsCost();
            goodsCost.setId(UuidUtils.getUUID());
            goodsCost.setGoodsId(hgv.getGoodsId());
            goodsCost.setNumber(number);
            goodsCost.setTotalAmount(amount);
            goodsCost.setCompanyId(vo.getCompanyId());
            goodsCostList.add(goodsCost);
        }
        goodsCostMapper.insertBatch(goodsCostList);
    }

    /**
     * 处理待入库单
     * @param type 1新增单据 2-作废单据
     * @param vo
     */
    private void processHouseWaitIn(int type, HouseInVo vo) {
        Map<String, HouseInGoodsVo> map = new HashMap<>();
        if (!Utils.isEmpty(vo.getHouseInGoodsVoList())) {
            List<HouseWaitInGoods> newList = new ArrayList<>();
            for (HouseInGoodsVo hgv : vo.getHouseInGoodsVoList()) {
                HouseWaitInGoods hwg = new HouseWaitInGoods();
                hwg.setId(hgv.getHouseWaitInGoodsId());
                hwg.setHouseWaitInId(vo.getHouseWaitInId());
                hwg.setGoodsId(hgv.getGoodsId());
                hwg.setHasInNumber(type == 1 ? hgv.getNumber() : hgv.getNumber().negate());
                hwg.setWaitInNumber(type == 1 ? hgv.getNumber().negate() : hgv.getNumber());
                hwg.setNumber(hgv.getNumber());
                hwg.setUnitId(hgv.getUnitId());
                hwg.setTimes(hgv.getTimes());
                hwg.setCompanyId(vo.getCompanyId());
                newList.add(hwg);
            }
            houseWaitInGoodsMapper.insertBatch(newList);
        }

        if (!Utils.isEmpty(vo.getHouseInPacketVoList())) {
            List<HouseWaitInPacket> newList = new ArrayList<>();
            for (HouseInPacketVo hgv : vo.getHouseInPacketVoList()) {
                HouseWaitInPacket hwg = new HouseWaitInPacket();
                hwg.setId(hgv.getHouseWaitInPacketId());
                hwg.setHouseWaitInId(vo.getHouseWaitInId());
                hwg.setRefundPacketId(hgv.getRefundPacketId());
                hwg.setPacketId(hgv.getPacketId());
                hwg.setPacketNo(hgv.getPacketNo());
                hwg.setPacketName(hgv.getPacketName());
                hwg.setHasInNumber(type == 1 ? hgv.getNumber() : hgv.getNumber().negate());
                hwg.setWaitInNumber(type == 1 ? hgv.getNumber().negate() : hgv.getNumber());
                hwg.setNumber(hgv.getNumber());
                hwg.setCompanyId(vo.getCompanyId());
                newList.add(hwg);
            }
            houseWaitInPacketMapper.insertBatch(newList);
        }

        long totalWaitInNumber = houseWaitInGoodsMapper.countWaitInNumber(vo.getHouseWaitInId()) + houseWaitInPacketMapper.countWaitInNumber(vo.getHouseWaitInId());
        long number = houseWaitInGoodsMapper.countNumber(vo.getHouseWaitInId()) + houseWaitInPacketMapper.countNumber(vo.getHouseWaitInId());
        HouseWaitIn houseWaitIn = new HouseWaitIn();
        houseWaitIn.setId(vo.getHouseWaitInId());
        if (totalWaitInNumber == 0) {
            //待入库单全部入库
            houseWaitIn.setStatus(3);
        } else {
            if (totalWaitInNumber == number) {
                //待入库
                houseWaitIn.setStatus(1);
            } else {
                //部分入库
                houseWaitIn.setStatus(2);
            }
        }
        houseWaitInMapper.updateById(houseWaitIn);
    }
}
